#ifndef COLLISIONSHAPES_H
#define COLLISIONSHAPES_H

#include <QObject>

class AbstractObject;
class CollisionShapesDocument;
class CollisionPoly;

class CollisionShape : public QObject
{
    Q_OBJECT

public:
    enum Type
    {
        Unknown,
        Rectangle,
        Circle,
        Polygon
    };

    CollisionShape();

    virtual void draw(QPointer<CollisionShapesDocument> csDoc, QPainter& painter) const = 0;
    virtual QRectF rect() const = 0;
    virtual QPainterPath shape() const = 0;

    QPointer<AbstractObject> shapeOwner() const { return m_shapeOwner; }

    Type type() const;

    virtual QList<QPointer<CollisionPoly> > toPolygon(QPointer<CollisionShapesDocument> csDoc, int numIterations = 1) const = 0;

    QPointer<QWidget> propertiesWidget() const { Q_ASSERT(m_propertiesWidget); return m_propertiesWidget; }

    void setPhysicsParams(float friction, float restitution, float density);
    void physicsParams(float& friction, float& restitution, float& density);
protected:
    Type m_type;
private:
    QPointer<AbstractObject> m_shapeOwner;
    QPointer<QWidget> m_propertiesWidget;

    // physics parameters
    float m_fFriction;
    float m_fRestitution;
    float m_fDensity;
signals:
    void shapeChanged();
public slots:
    void setShapeOwner(QPointer<AbstractObject> owner);
};

class CollisionBox : public CollisionShape
{
    Q_OBJECT
public:
    CollisionBox(const QRectF& rect);

    void draw(QPointer<CollisionShapesDocument> csDoc, QPainter& painter) const;
    static void drawRect(QPainter& painter, const QRectF &rect, const QPen &pen);

    QRectF rect() const;
    QPainterPath shape() const;

    const QRectF boxRect() const {return m_boxRect; }

    QList<QPointer<CollisionPoly> > toPolygon(QPointer<CollisionShapesDocument> csDoc, int numIterations = 1) const;
private:
    // Box2D uses halfWidth and halfHeight
    QRectF m_boxRect;
public slots:
    void setBoxRect(const QRectF& rect);
};

class CollisionCircle : public CollisionShape
{
    Q_OBJECT
public:
    CollisionCircle(QPointF center, float radius);

    void draw(QPointer<CollisionShapesDocument> csDoc, QPainter& painter) const;
    static void drawCircle(QPainter& painter, const QPointF& center, float radius, const QPen &pen);

    QRectF rect() const;
    QPainterPath shape() const;

    QPointF center() const { return m_center; }
    float radius() const { return m_fRadius; }

    void setCenter(float x, float y);
    void setRadius(float r);

    QList<QPointer<CollisionPoly> > toPolygon(QPointer<CollisionShapesDocument> csDoc, int numIterations = 1) const;
private:
    QPointF m_center;
    float m_fRadius;
};

class CollisionPoly : public CollisionShape
{
    Q_OBJECT
public:
    CollisionPoly(const QPolygonF& poly);

    void draw(QPointer<CollisionShapesDocument> csDoc, QPainter& painter) const;
    static void drawPoly(QPainter& painter, const QPolygonF& poly, const QPen &pen);

    QRectF rect() const;
    QPainterPath shape() const;

    const QPolygonF& poly() const { return m_poly; }
    void setPoly(const QPolygonF& poly);

    QList<QPointer<CollisionPoly> > toPolygon(QPointer<CollisionShapesDocument> csDoc, int numIterations = 1) const;
private:
    QPolygonF m_poly;
};

#endif // COLLISIONSHAPES_H
